/*
 * Contains lobby screen code
 */

#include <string.h>
#include <stdbool.h>
#include "main.h"
#include "network.h"
#include "world/player.h"
#include "util/log.h"
#include "game.h"

#define MIN_PLAYERS 1

StoCmessage netmessage; // For communications to clients
CtoSmessage received;  // For communications to clients

static int count_clients ();

void lobby_init ()
{
	network_init (0);
}

void send_readystatus (int client, bool ready)
{
	netmessage.type = ready ? StoC_LOBBY_CLIENTREADY : StoC_LOBBY_CLIENTNOTREADY;
	netmessage.clientidx = client;
	send_StoCmessage (&netmessage, -1);
}

bool all_players_are_ready ()
{
	int readycount = 0;
	for (int i = 0; i < MAX_CLIENTS; i++) {
		if (*the_network.client[i].nickname != '\0') { // cl. exists
			if (the_network.client[i].ready) readycount++;
			else return false;
		}
	}
	
	if (readycount >= MIN_PLAYERS) return true;
	else return false;
}

void lobby_update ()
{
	int sender;
	
	receive_CtoSmessage (&received, &sender);
	while (received.type != CtoS_NOMSG) {
		switch (received.type) {
			
		case CtoS_LOBBY_READY:
			the_network.client[sender].ready = 1;
			send_readystatus (sender, the_network.client[sender].ready);
			if (all_players_are_ready()) {
				unsigned long seed = time(0);
				for (int i = 0; i < MAX_CLIENTS; i++) seed ^= the_network.client[i].uid;
				
				// FIXME: assumes that each client has exactly one player
				// FIXME: assumes that each player controls exactly one character
				int n_characters = count_clients ();
				
				netmessage.type = StoC_LOBBY_SEEDGAME;
				netmessage.seed = seed;
				netmessage.n_characters = n_characters;
				send_StoCmessage (&netmessage, -1);
				
				game_seed (seed, n_characters);
				change_state (STATE_GAME); // players are ready, go in-game
				
				netmessage.type = StoC_LOBBY_STARTGAME;
				send_StoCmessage (&netmessage, -1);
				return; // get out of here to be safe from gamestate-consistency errors
			}
			break;
		
		case CtoS_LOBBY_NOTREADY:
			the_network.client[sender].ready = 0;
			send_readystatus (sender, the_network.client[sender].ready);
			break;

		case CtoS_CHAT:
			netmessage.type = StoC_CHAT;
			strcpy (netmessage.line, received.line);
			send_StoCmessage (&netmessage, -1);
			break;
		
		default:
			log_error ("Received unidentified message type %d from client.", received.type);
			break;
			
		}
		
		receive_CtoSmessage (&received, &sender);
	}
}

void lobby_cleanup ()
{
	// nothing to do on server.
	// This function exists for compatibility with client lobby interface.
}

static int count_clients ()
{
	int n_clients = 0;
	
	for (int i = 0; i < MAX_CLIENTS; i++) {
		if (*the_network.client[i].nickname != '\0') { // cl. exists
			n_clients++;
		}
	}
	
	return n_clients;
}
